﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using System.Linq;
using System.Threading;

namespace qip_history_synchronizer
{
    class HistoryUtils
    {
        const string incBreak = "--------------------------------------<-";
        const string outBreak = "-------------------------------------->-";
        //-------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Позволяет получить список категорий опций из файла: 
        /// </summary>
        /// <param name="p_sFileName">имя файла</param>
        /// <returns>список категорий</returns>
        public static List<string> getFileContent(string p_sFileName)
        {
            List<string> fileContent = new List<string>();
            using (StreamReader objReader = new StreamReader(p_sFileName, Encoding.Default))
            {
                while (objReader.Peek() >= 0)
                {
                    string sLine = objReader.ReadLine();
                    fileContent.Add(sLine);
                }
            }

            return fileContent;
        }

        //-------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Получаем список файлов с историями
        /// </summary>
        /// <param name="p_sPath">папка с историей QIP</param>
        /// <returns>контент файла в виде списка строк</returns>
        public static List<string> getQIPHistoryFileNames(string p_sPath, string p_sProfile)
        {
            string path = p_sPath + @"\Users\" + p_sProfile + @"\History";

            string[] arrAllFiles = Directory.GetFiles(path);
            List<string> files = new List<string>(arrAllFiles);

            if (files.Contains(path + @"\_srvlog.txt"))
                files.Remove(path + @"\_srvlog.txt");

            return files;
        }

        //-------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Получить контент файлов в виде хэштаблицы
        /// </summary>
        /// <param name="files">список файлов</param>
        /// <returns>файл-ключ / содержание</returns>
        public static Hashtable getFilesContent(List<string> files)
        {
            Hashtable htFilesContent = new Hashtable();
            foreach( string file in files )
            {
                htFilesContent.Add( file, getFileContent(file) );
            }
            return htFilesContent;
        }

        //-------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Возращает контент файла из списка строк
        /// </summary>
        /// <param name="lines">список строк файла</param>
        /// <returns>содержание файла с разделителями</returns>
        public static string getContentFromLines(List<string> lines)
        {
            string content = String.Empty;
            foreach( string line in lines )
            {
                content += line + Environment.NewLine;
            }
            content = content.Substring(0, content.LastIndexOf("\r\n"));
            return content;
        }

        //-------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Получение хэшсписка истории
        /// </summary>
        /// <param name="content">содержимое файла</param>
        /// <returns>блоки сообщений</returns>
        public static Hashtable getHistoryHashtable(List<string> content)
        {
            Hashtable block = new Hashtable();

            for( int i = 0; i < content.Count; i++ )
            {
                string str = content[i];
                if( str == incBreak || str == outBreak )
                {
                    i++;
                    string data = content[i];
                    i++;
                    string breaker = content[i];
                    List<string> tmpList = new List<string>();
                    while (i < content.Count - 1 && (breaker != incBreak && breaker != outBreak))
                    {
                        tmpList.Add(content[i]);
                        i++;
                        breaker = content[i];
                    }

                    if( str == incBreak && !block.Contains( "-->>--" + data ) )
                        block.Add( "-->>--" + data, tmpList );
                    else
                        if( !block.Contains( "--<<--" + data ) )
                        block.Add("--<<--" + data, tmpList);
                    i--;
                }
            }

            return block;
        }

        //-------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Получение упорядоченного списка истории
        /// </summary>
        /// <param name="content">содержимое файла</param>
        /// <returns>хронологически упорядоченный список сообщений</returns>
        public static List<Message> getHistoryOrderlyList(List<string> content)
        {
            List<Message> result = new List<Message>();

            Hashtable inc = new Hashtable();

            for (int i = 0; i < content.Count; i++)
            {
                string str = content[i];
                if (str == incBreak || str == outBreak)
                {
                    i++;
                    string data = content[i];
                    i++;
                    string breaker = content[i];

                    List<string> tmpList = new List<string>();
                    while (i < content.Count - 1 && (breaker != incBreak && breaker != outBreak))
                    {
                        tmpList.Add(content[i]);
                        i++;
                        breaker = content[i];
                    }

                    //парсим дату:
                    string sDate = data.Substring(data.IndexOf("(") + 1, data.LastIndexOf(")") - 1 - data.IndexOf("("));
                    DateTime dtMessageData = DateTime.Now;
                    try
                    {
                        dtMessageData = DateTime.Parse(sDate);
                    }
                    catch(Exception e){}

                    //парсим ник:
                    string nick = data.Substring( 0, data.IndexOf( "(" ) - 1 );

                    if(str == incBreak)
                        result.Add(new Message(Message.TYPE.IN, dtMessageData, nick, getArrayToString(tmpList.ToArray())));
                    else
                        result.Add(new Message(Message.TYPE.OUT, dtMessageData, nick, getArrayToString(tmpList.ToArray())));
                    i--;
                }
            }

            return result;
        }

        //-------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Получить строку из массива
        /// </summary>
        /// <param name="arr">массив строк</param>
        /// <returns>строка с разделителями</returns>
        public static string getArrayToString(string[] arr)
        {
            string result = "";
            foreach( string str in arr )
            {
                result += str + Environment.NewLine;
            }

            result = result.Substring(0, result.LastIndexOf( "\r\n" ) );

            return result;
        }

        //-------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Получить историю за всю дату
        /// </summary>
        /// <param name="messageList">список сообщений</param>
        /// <returns>содержимое</returns>
        public static string getContentFromList(List<Message> messageList)
        {
            string result = "";
            CultureInfo ci = new CultureInfo("en-US");

            foreach( Message message in messageList )
            {
                if (message.M_TYPE == Message.TYPE.IN)
                    result += incBreak;
                else
                    result += outBreak;

                
                result += Environment.NewLine;
                //TODO: переделать на культуринфо полностью
                result += message.CONTACT + " (" + message.DATE.ToLongTimeString(  ) + " " + message.DATE.ToString("d", ci) + ")";
                result += Environment.NewLine;
                result += message.MESSAGE;
                result += Environment.NewLine;
            }

            return result;
        }

        //-------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Получить историю за период
        /// </summary>
        /// <param name="messageList">список сообщений</param>
        /// <param name="dtBegin">дата начала</param>
        /// <param name="dtEnd">дата конца</param>
        /// <returns>содержимое</returns>
        public static string getContentFromListByPeriod(List<Message> messageList, DateTime dtBegin, DateTime dtEnd)
        {
            var selectedMess = from m in messageList
                               where m.DATE >= dtBegin && m.DATE <= dtEnd
                               select m;

            List <Message> mesArr = selectedMess.ToList();

            string result = getContentFromList(mesArr);
            return result;
        }


        //-------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Синхронизация историй
        /// </summary>
        /// <param name="messFrom"></param>
        /// <param name="messTo"></param>
        /// <returns></returns>
        public static List<Message> synchronize( List<Message> messFrom, List<Message> messTo )
        {
            List<Message> result = new List<Message>( messTo.ToArray() );

            foreach( Message message in messFrom )
            {
                if( !message.ContaisInList( result ) )
                {
                    var selectedMessageSet = from mess in result
                                             where mess.DATE <= message.DATE
                                             orderby message.DATE
                                             select mess;

                    if( selectedMessageSet.ToList().Count > 0 )
                    {
                        Message lastMessage = selectedMessageSet.Last();
                        if( lastMessage != null )
                        {
                            int positionToInsert = result.IndexOf( lastMessage );
                            result.Insert( positionToInsert + 1, message );
                        }
                    }

                }
            }

            return result;
        }

        //-------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// Получить контент в виде списка строк
        /// </summary>
        /// <param name="p_sContant"></param>
        /// <returns></returns>
        public static List<string> getContantInList( string p_sContant )
        {
            List<string> lResult = new List<string>();
            string[] splitContant = p_sContant.Split( new string[1]{"\r\n"}, StringSplitOptions.RemoveEmptyEntries );
            lResult.AddRange( splitContant );
            return lResult;
        }

        //-------------------------------------------------------------------------------------------------------------
        public static bool CompareMessagesLists( List<Message> messageList1, List<Message> messageList2 )
        {
            foreach( Message message in messageList1 )
            {
                if( !message.ContaisInList( messageList2 ) )
                    return false;
            }
            return true;
        }
    }
}